package com.cxyd.modules.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cxyd.common.Utils.BeanUtils;
import com.cxyd.common.constant.Constant;
import com.cxyd.common.constant.enums.wms.PostWcsStEnum;
import com.cxyd.common.exception.RootException;
import com.cxyd.common.page.PageData;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ConvertUtils;
import com.cxyd.modules.core.service.SerialNumberService;
import com.cxyd.modules.security.user.SecurityUser;
import com.cxyd.modules.security.user.UserDetail;
import com.cxyd.modules.sys.dto.SysUserDTO;
import com.cxyd.modules.wms.dao.ContainerDao;
import com.cxyd.modules.wms.dao.PostWcsBakDao;
import com.cxyd.modules.wms.dao.PostWcsDao;
import com.cxyd.modules.wms.dto.PostWcsDTO;
import com.cxyd.modules.wms.dto.TaskDTO;
import com.cxyd.modules.wms.entity.ContainerEntity;
import com.cxyd.modules.wms.entity.PostWcsBakEntity;
import com.cxyd.modules.wms.entity.PostWcsEntity;
import com.cxyd.modules.wms.entity.TaskEntity;
import com.cxyd.modules.wms.service.PostWcsService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 设备任务
 *
 * @author g_Cycle gengruyi01@163.com
 * @since 1.0.0 2023-04-27
 */
@Service
public class PostWcsServiceImpl extends CrudServiceImpl<PostWcsDao, PostWcsEntity, PostWcsDTO> implements PostWcsService {
    private final PostWcsDao postWcsDao;
    private final ContainerDao containerDao;
    private final SerialNumberService serialNumberService;
    private final PostWcsBakDao postWcsBakDao;

    public PostWcsServiceImpl(PostWcsDao postWcsDao, ContainerDao containerDao, SerialNumberService serialNumberService, PostWcsBakDao postWcsBakDao) {
        this.postWcsDao = postWcsDao;
        this.containerDao = containerDao;
        this.serialNumberService = serialNumberService;
        this.postWcsBakDao = postWcsBakDao;
    }

    @Override
    public PageData<PostWcsDTO> page(Map<String, Object> params) {
        //1.获取任务信息
        final IPage<PostWcsEntity> page = baseDao.selectPage(
                getPage(params, "post_id", false),
                getWrapper(params));
        return getPageData(page, PostWcsDTO.class);
    }

    @Override
    public QueryWrapper<PostWcsEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("id");
        String contNo = (String) params.get("contNo");
        String fromPos = (String) params.get("fromPos");
        String tosPos = (String) params.get("tosPos");
        QueryWrapper<PostWcsEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);
        wrapper.like(StringUtils.isNotBlank(contNo), "cont_no", contNo);
        wrapper.like(StringUtils.isNotBlank(fromPos), "frm_pos", fromPos);
        wrapper.like(StringUtils.isNotBlank(tosPos), "to_pos", tosPos);
        return wrapper;
    }


    @Override
    public void updateByPk(Map<String, Object> params) {
        String requestPk = (String) params.get("pk");
        String code = (String) params.get("code");
        String msg = (String) params.get("msg");
        final UpdateWrapper<PostWcsEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("request_pk", requestPk);
        updateWrapper.set("trk_st", ("0".equals(code)) ? 1 : 9);
        updateWrapper.set("ack_code", code);
        updateWrapper.set("ack_msg", msg);
        updateWrapper.set("updater", Constant.ClientCode.WMS.getId());
        updateWrapper.set("update_date", new Date());
        baseDao.update(null, updateWrapper);
    }

    @Override
    public PostWcsDTO getOneRecord() {
        PostWcsEntity entity = baseDao.getOneRecord();
        return ConvertUtils.sourceToTarget(entity, PostWcsDTO.class);
    }

    /**
     * 搬送指令 proc_wms_post_wcs_insert
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void postWcsInsert(PostWcsEntity insertPostWcs) {
        //查看任务是否存在
        String contNo = insertPostWcs.getContNo();
        List<PostWcsEntity> postWcsEntities = postWcsDao.selectList(new QueryWrapper<PostWcsEntity>()
                .eq("trk_st", PostWcsStEnum.INITIAL.getCode())
                .eq("cont_no", contNo));
        if (!CollectionUtils.isEmpty(postWcsEntities)) {
            String msg = "托盘[" + contNo + "]已存在搬送任务!";
            throw new RootException(msg);
        }
        //获取PK流水号 proc_serial_number_get
        String requestPk = serialNumberService.getSerialNumberByCode("requestPk");
        insertPostWcs.setRequestPk(requestPk);
        if (StringUtils.isBlank(insertPostWcs.getContType())) {
            ContainerEntity containerEntity = containerDao.selectOne(new QueryWrapper<ContainerEntity>().eq("cont_no", contNo));
            insertPostWcs.setContType(containerEntity.getContType());
        }
        postWcsDao.insert(insertPostWcs);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void backUp(Date date, Integer num) {
        while (true) {
            List<PostWcsEntity> postWcsEntities = postWcsDao.selectForBackup(date, num);
            if (CollectionUtils.isEmpty(postWcsEntities)) {
                return;
            }
            List<PostWcsBakEntity> list = new ArrayList<>();
            for (PostWcsEntity postWcs : postWcsEntities) {
                PostWcsBakEntity postWcsBak = new PostWcsBakEntity();
                BeanUtils.copyProperties(postWcs, postWcsBak);
                list.add(postWcsBak);
            }
            postWcsBakDao.batchInsert(list);
            List<Long> ids = postWcsEntities.stream().map(PostWcsEntity::getPostId).collect(Collectors.toList());
            postWcsDao.deleteBatchIds(ids);
        }
    }

    @Override
    public void commandResend(Long postId) {
        PostWcsEntity postWcsEntity = postWcsDao.selectById(postId);
        UserDetail user = SecurityUser.getUser();
        if (ObjectUtils.isEmpty(postWcsEntity)) {
            throw new RootException("指令不存在");
        }
        if (PostWcsStEnum.FAIL.getCode() != postWcsEntity.getTrkSt()) {
            throw new RootException("只有失败的任务才可以重发");
        }
        PostWcsEntity updatePost = new PostWcsEntity();
        updatePost.setPostId(postId);
        updatePost.setTrkSt(PostWcsStEnum.INITIAL.getCode());
        updatePost.setUpdater(user.getId());
        updatePost.setUpdateDate(new Date());
        updatePost.setComments("指令重发");
        postWcsDao.updateById(updatePost);
    }
}